package com.shengsiyuan.netty.sixthexample.handler;

import com.google.protobuf.MessageLite;
import com.shengsiyuan.netty.sixthexample.proto.MyDataInfo;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * Created by deng_wb on 2019/8/5
 */
public class CustomProtobufDecoder extends ByteToMessageDecoder  {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

        while (in.readableBytes()>4){
            in.markReaderIndex();
            // 获取包头中body的长度
            byte low = in.readByte();
            byte heigh = in.readByte();
            short s0 = (short) (low & 0xff);
            short s1 = (short) (heigh & 0xff);
            s1 <<= 8;
            short length = (short) (s0 | s1);
            System.out.println("length is : "+length);
            // 获取包头中的protobuf类型
            in.readByte();
            byte dataType = in.readByte();

            // 如果可读长度小于body长度，恢复读指针，退出。
            if (in.readableBytes() < length) {
                in.resetReaderIndex();
                return;
            }
            // 读取body
            ByteBuf bodyByteBuf = in.readBytes(length);

            byte[] array;
            int offset;

            int readableLen= bodyByteBuf.readableBytes();
            if (bodyByteBuf.hasArray()) {
                array = bodyByteBuf.array();
                offset = bodyByteBuf.arrayOffset() + bodyByteBuf.readerIndex();
            } else {
                array = new byte[readableLen];
                bodyByteBuf.getBytes(bodyByteBuf.readerIndex(), array, 0, readableLen);
                offset = 0;
            }

            //反序列化
            MessageLite result = decodeBody(dataType, array, offset, readableLen);
            out.add(result);

        }

    }

    public MessageLite decodeBody(byte dataType, byte[] array, int offset, int length)throws Exception{
        if (dataType == 0x00){
            return MyDataInfo.Person.getDefaultInstance()
                    .getParserForType().parseFrom(array,offset,length);
        }else if (dataType == 0x01){
            return MyDataInfo.Teacher.getDefaultInstance()
                    .getParserForType().parseFrom(array,offset,length);
        }else if (dataType == 0x02){
            return MyDataInfo.Student.getDefaultInstance()
                    .getParserForType().parseFrom(array,offset,length);
        }
        return null;
    }
}
